package cn.itsource.service.impl;

import cn.itsource.bean.Department;
import cn.itsource.bean.Employee;
import cn.itsource.config.PageList;
import cn.itsource.mapper.DepartmentMapper;
import cn.itsource.query.DepartmentQuery;
import cn.itsource.service.IDepartmentService;
import cn.itsource.service.IEmployeeService;
import cn.itsource.util.JsonResult;
import cn.itsource.util.MyUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author : 张金铭
 * @description :
 * @create :2022-11-07 11:57:00
 */
@Slf4j
@Service
public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Department> implements IDepartmentService {

    @Resource
    private IEmployeeService employeeService;

    @Resource
    private DepartmentMapper departmentMapper;





    @Override
    public JsonResult getPage(DepartmentQuery query) {
        //1.获取条件
        String key = query.getKeyword();
        //2.获取原始分页
        Page<Department> pageKey = new Page<>(query.getPage(),query.getRows());

        //3.查询条件
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotEmpty(query.getKeyword()),Department::getName,query.getKeyword());
//        queryWrapper.or().like(StringUtils.isNotEmpty(query.getKeyword()),Department::getSn,query.getKeyword());
        queryWrapper.eq(query.getParentId()!=null,Department::getParentId,query.getParentId());
        queryWrapper.orderByAsc(Department::getSn);

        //4.获取添加条件后的分页数据
        Page<Department> departmentPage = this.page(pageKey, queryWrapper);
        //4.1取出具体数据
        List<Department> records = departmentPage.getRecords();



//        List<Department> departments = null;

        List<Department> collect = records.stream().map(item -> {
        //5.通过流将每个具体数据的管理者的id取出，并查询到管理者名字，再写入具体数据
            Long managerId = item.getManagerId();
            if (managerId!=null) {
                Employee byId = employeeService.getById(managerId);
                item.setUserName(byId.getUsername());
            }
        //6.通过流将每个具体数据的上级部门的的id取出，并查询到上级部门名字，再写入具体数据
            Long parentId = item.getParentId();
            if (parentId!=null){
                Department byId = this.getById(parentId);
                if (byId!=null) {
                    item.setParentName(byId.getName());
                }
            }
            return item;
        }).collect(Collectors.toList());

        //做数据封装
        PageList<Department> pageList = new PageList<>();
        pageList.setList(collect);
        pageList.setTotal(departmentPage.getTotal());
//        System.out.println(departmentPage.getTotal());
        return JsonResult.success(pageList);
    }

    @Override
    public JsonResult updateState(Department department) {
        Department departmentById = this.getById(department.getId());
        if(department.getState()!=null) {
            departmentById.setState(department.getState().equals(1) ? 0 : 1);
        }else {
            departmentById.setState(0);
        }
        boolean byId = this.updateById(departmentById);
        if (byId){
            return JsonResult.success();
        }else {
            return JsonResult.error("更新失败");
        }
    }

    @Override
    public boolean getId(Department department) {
        //插入后会自动在实体类填充id，此时取出id将id拼接到dir再次更新即可
        Integer insert = departmentMapper.insert(department);
        if (insert!=1){
            return false;
        }
        //取出id
        Long id = department.getId();
        String newDirPath = "";
        //拼接到dir后
        if (!department.getDirPath().equals("/")) {
            newDirPath = department.getDirPath()+"/"+ id;
        }else {
            newDirPath =department.getDirPath()+id;
        }
        department.setDirPath(newDirPath);
        //再次存入
        boolean byId = this.updateById(department);
        return byId;
    }

    @Override
    public JsonResult getFirst() {
        List<Department> allFirst = departmentMapper.getAllFirst();
        //二次封装
        List<Department> collect = allFirst.stream().map(item -> {
            Department department = new Department();
            department.setName(item.getName());
            department.setId(item.getId());
            return department;
        }).collect(Collectors.toList());

        return JsonResult.success(collect);
    }



    @Override
    @Transactional
    public boolean removerTree(Long id) {
        this.getSonId(id,new ArrayList<Long>());
            //在将他的直属下级的id取出，在表里查询是否有对应的直属下级的下级
        return true;
    }


    /**
     * 递归计算子级并删除
     * @param id
     * @param arrayList
     */
    @Override
    public void getSonId(Long id,List<Long> arrayList) {
        if (id!=null){
            arrayList.add(id);
        }
        for (Long myId:arrayList
        ) {
            LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();
            //获取所有的直属下级部门的id  collect
            queryWrapper.eq(Department::getParentId, myId);
            List<Department> list = this.list(queryWrapper);
            //有子级，取出子级的id，准备再次遍历
            List<Long> collect = null;
            if (list!=null&&list.size()!=0) {
                //有子级，取出子级的id，准备再次遍历
                collect = list.stream().map(item -> {
                    Long sonId = item.getId();
                    return sonId;
                }).collect(Collectors.toList());
                //删除本id的数据
                this.removeById(myId);
                this.getSonId(null,collect);
            }else {
                //删除本id的数据
                this.removeById(myId);
            }

        }

    }

    @Override
    @Transactional
    public void updateAllDir(Department department) {
        //获取上级部门号
        List<Long> parentInts = department.getParentInts();

        //判断是否有上级部门
        if (parentInts!=null&&parentInts.size()>0) {
            Long lastInts = parentInts.get(parentInts.size() - 1);
            department.setParentId(lastInts);
        }else {
            //若没有上级部门
            department.setParentId(null);
        }

        //将转换路径，调用封装好的方法   将数组转换成   /xxx/xxx/xx格式
        String dirPath = MyUtils.getDir(parentInts);
        dirPath =  dirPath.equals("/")?"":dirPath;
        department.setDirPath(dirPath+"/"+department.getId());

        //这里拿到第一个的id和dirPath
        Long id = department.getId();
        String path = department.getDirPath();
        //创建一个集合,装上级id
        ArrayList<Long> ids = new ArrayList<>();
        ids.add(id);


        //获取到子级,List ，遍历子级，更新子级的dir
        //将子级的id和dir重新投入方法
        updateUtil(department.getDirPath(),ids);
        this.updateById(department);
    }


    /**
     * 递归解决父部门更改后，子部门dirPath同步更改
     * @param dirPath
     * @param ids
     */
    @Override
    public void updateUtil(String dirPath,List<Long> ids) {
        //将id到数据库查询子级数据
        //若传进来的子级部门id为空，说明没有子级，直接返回即可
        if (ids==null){
            return;
        }

        //遍历所有的子级id
        for (Long id: ids
             ) {
            //查询子级的子级数据
            LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Department::getParentId, id);
            List<Department> list = this.list(queryWrapper);


            //有子级，取出子级的id，准备再次遍历  collect是装子级的子级id的
            List<Long> collect = null;
            if (list!=null&&list.size()!=0) {
                //有子级，取出子级的id，准备再次遍历
                collect = list.stream().map(item -> {
                    Long sonId = item.getId();
                    return sonId;
                }).collect(Collectors.toList());

                //更改子级的dir   此时的dir应该是 dirPath + "/" +this.id
                List<Department> departments = list.stream().map(item -> {
                    item.setDirPath(dirPath + "/" + item.getId());
                    return item;
                }).collect(Collectors.toList());
                //更新所有的子级这些数据
                this.updateBatchById(departments);
                //再次调用  此时子级已经是相当于父级
                this.updateUtil(dirPath+"/"+id,collect);
            }
        }
    }


}
